# -*- coding: utf-8 -*-
# created on 2016/5/10


from mathsolver.functions.base import *
from sympy import solveset, together, factor, Abs


# 代入计算
class DaiRu(BaseFunction):
    def solver(self, *args):
        """
        DaiRu().solver(BasePoly("e**x"), BaseSymbolValue({"x": ["1","-1","0"]}))
        :param args:
        :return:
        """
        expr = args[0].sympify()
        pairs = args[1].value2pairs()
        for pair in pairs:
            self.steps.append(["将%s代入代数式，得：" % self.output_symbol_value(pair), new_latex(expr)])

            symbol_replace = {}
            for symbol, value in pair.items():
                if value.is_Number and value.is_positive:
                    symbol_replace[symbol] = new_latex(value)
                else:
                    symbol_replace[symbol] = "(%s)" % new_latex(value)

            self.steps.append(["", "= %s" % new_latex(expr)])

            new_expr = expr.subs(pair)

            new_expr = new_expr.cancel()
            self.steps.append(["", "= %s" % new_latex(new_expr)])

            if len(new_expr.free_symbols) > 0:  # and new_expr.free_symbols != expr.free_symbols:
                value = BasePoly(new_expr)
                value.intermediate = False
                self.output.append(value)
            else:
                value = simplify(new_expr)
                if str(value) != str(new_expr):
                    self.steps.append(["", "= %s" % new_latex(value)])
                self.output.append(BaseNumber(value))

        self.label.add("代入计算")

        return self


# 因式分解
class YinShiFenJie(BaseFunction):
    def solver(self, *args):
        """
        YinShiFenJie().solver(BasePoly("x**2-2*x*y+y**2-1"))
        :param args:
        :return:
        """
        expr = args[0].sympify()
        self.steps.append(["", "%s" % new_latex(expr)])
        expr_factor = expr.factor()
        if expr_factor != expr:
            self.steps.append(["", "= %s" % new_latex(expr_factor)])
            expr = expr_factor

        self.output.append(BaseNumber(expr))
        self.label.add("因式分解")
        return self


class TianKong(BaseFunction):
    def solver(self, *args):
        """
        TianKong().solver(BaseEq(["(2*b)/(2*a)","(UNK)/(a)"]))
        :param args:
        :return:
        """
        f1, f2 = args[0].sympify()
        target_sym = sympify("UNK")

        answer = solveset(f1 - f2, target_sym)
        self.steps.append(["", self.output_eq([f1, f2]).replace("UNK", "()")])
        self.steps.append(["答：", ",".join([new_latex(ans) for ans in answer])])
        return self


class ShuYuShiDaiShuShiQiaoSuan2(BaseFunction):
    def fenshi_fangcheng(self, expr):
        """
        判断方程中是否含有分式
        :param expr:
        :return: 含有分式-True，不含分式-False
        """
        if expr.is_Add:
            for item_expr in expr.args:
                result = self.fenshi_fangcheng(item_expr)
                if result:
                    return True
            return False
        elif expr.is_Mul:
            for item_expr in expr.args:
                if self.fenshi_fangcheng(item_expr):
                    return True
            return False
        elif expr.is_Pow:
            if expr.args[1] == -1:
                return True
            return False
        elif expr.is_Number or expr.is_Symbol or isinstance(expr, Abs):
            return False
        else:
            ValueError('unexpected situation!')

    def eq_huajian(self, eq):
        """
        化简等式
        :param eq:
        :return: 化简后的表达式
        """
        left_expr, right_expr = eq[0], eq[1]
        left_expr = together(left_expr)
        if left_expr.is_Mul:
            for item_expr in left_expr.args:
                if item_expr.is_Pow and item_expr.args[1] == -1:
                    fenmu = item_expr.args[0]
                    left_expr = left_expr * fenmu
                    right_expr = right_expr * fenmu
            t = factor(left_expr - right_expr)
            if t.is_Pow and t.args[1].is_Integer and t.args[1] % 2 == 0:
                left_expr, right_expr = t.args[0].args[0], -t.args[0].args[1]
            self.steps.append(
                ['因为%s=%s，' % (new_latex(eq[0]), new_latex(eq[1])), '所以%s=%s' % (new_latex(left_expr), new_latex(right_expr))])
        return left_expr, right_expr

    @staticmethod
    def tongleixing_xishu(expr):
        """
        获取表达式中系数相等的项前面的系数
        :param expr: 表达式
        :return: 相等的系数
        """
        canshu = 1
        symbols = expr.free_symbols
        x_symbol = symbols.pop()
        y_symbol = symbols.pop()
        sub_expr = 0
        for item_expr in expr.args:
            if len(item_expr.free_symbols) == 2:
                continue
            sub_expr = sub_expr + item_expr
        if sub_expr == 0:
            return canshu
        if sub_expr.coeff(x_symbol) == sub_expr.coeff(y_symbol) or sub_expr.coeff(x_symbol) + sub_expr.coeff(
                y_symbol) == 0:
            canshu = sub_expr.coeff(x_symbol)
        if canshu == 0:
            canshu = 1
        return canshu

    def solver(self, *args):
        """
        已知方程，求代数的值.
        :param args:
        :return:
        """
        eq = args[0].sympify()
        expr = args[1].sympify()
        if self.fenshi_fangcheng(eq[0]):
            left_expr, right_expr = self.eq_huajian(eq)
            fenzi_expr = expr.args[0]
            canshu = self.tongleixing_xishu(fenzi_expr)
            result = expr.subs(left_expr * canshu, right_expr * canshu)
            fenmu_expr = expr.args[1].args[0]
            canshu = self.tongleixing_xishu(fenmu_expr)
            result = result.subs(left_expr * canshu, right_expr * canshu)
            assert str(result) != str(expr)
            self.steps.append(['', '因此，最后公式的值是：%s' % new_latex(result)])
            self.output.append(BaseNumber(result))
        else:
            raise ValueError
        return self


if __name__ == '__main__':
    pass
